home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Audio / Patchmix / Source / PatchView.m < prev    next >
Text File  |  1992-08-18  |  18KB  |  635 lines

  1. // PatchView.m by Mara Helmuth
  2.  
  3. #import <math.h>
  4. #import <appkit/Application.h>
  5. #import <appkit/NXImage.h>
  6. #import <appkit/graphics.h>
  7. #import <appkit/Form.h>
  8. #import <appkit/Panel.h>
  9. #import <dpsclient/psops.h>
  10. #import <dpsclient/wraps.h>
  11.  
  12. #import "PatchWindow.h"
  13. #import "PatchView.h"
  14. #import "draw.h"
  15. #import "Oscil.h"
  16. #import "Arith.h"
  17. #import "Rand.h"
  18. #import "Out.h"
  19. #import "Evp.h"
  20. #import "Converter.h"
  21. #import "Buzz.h"
  22. #import "Reson.h"
  23. #import "Comb.h"
  24. #import "Pluck.h"
  25. #import "Allpass.h"
  26. //#import "Delay.h"
  27. //#import "Reverb.h"
  28. //#import "WS.h"
  29. #import "Instrum.h"
  30. #import "Param.h"
  31.  
  32.  
  33. @implementation PatchView
  34.  
  35. - initFrame:(const NXRect *)frameRect
  36. {
  37.     [super initFrame:frameRect];
  38.     
  39.     /* off-screen buffer */
  40.     screenImage = [[NXImage alloc] initSize:&bounds.size];
  41.         
  42.     return self;
  43. }
  44.  
  45.  
  46. - setImages        //  erase the patchview and make ugen images
  47. {
  48.  
  49.     [self erase:0];
  50.     
  51.     connecting = NO;
  52.     moving = NO;
  53.     setting = NO;
  54.     
  55.     PSInit();    // initialize postscript drawing defs
  56.     
  57.        return self;
  58. }
  59.  
  60. /* instance methods */
  61.  
  62. - windowChanged:newWindow
  63. {
  64.     NXRect    rect;
  65.     
  66.     [super windowChanged:newWindow];
  67.     
  68.   /* if our new window's an PatchWindow, we'll "register" ourself with it */
  69.     if ([newWindow respondsTo:@selector(registerRect:forView:)]) {
  70.       /* give the window our window-based coordinates */
  71.     rect = bounds;
  72.     [self convertRect:&rect toView:nil];
  73.     [newWindow registerRect:&rect forView:self];
  74.     }
  75.     
  76.     return self;
  77. }
  78.  
  79. - setUgen:(int)uType
  80. {
  81.     ugenType = uType;
  82.         return self;
  83. }
  84.  
  85.  
  86. - setDelegate:anObject
  87. {
  88.         delegate = anObject;
  89.         return self;
  90. }
  91.  
  92. - (BOOL)windowEntered:dragSource
  93. {
  94.  /* let our window know we've done some drawing */
  95.     return YES;
  96. }
  97.  
  98. - (BOOL)windowExited:dragSource    
  99. {
  100.   /* let our window know we've done some drawing */
  101.     return YES;
  102. }
  103.  
  104. - (BOOL)windowDropped:dragSource:(NXPoint *)currentLocation
  105. {
  106.   /* the user dropped a window into us */
  107.     [window flushWindow];
  108.     if ([delegate respondsTo:@selector(acceptedWindow:fromSource:)]) {
  109.     [delegate acceptedWindow:self fromSource:dragSource];
  110.     }
  111.  
  112.     // put the new ugen into the UnitGen ugenList
  113.     switch(ugenType) {
  114.         case 5: {
  115.             currentUgen = [[Arith alloc] init];
  116.             [currentUgen setAtype:'+'];
  117.             break;
  118.         }
  119.         case 6: {
  120.             currentUgen = [[Arith alloc] init];
  121.             [currentUgen setAtype:'-'];
  122.             break;
  123.         }
  124.         case 7: {
  125.             currentUgen = [[Arith alloc] init];
  126.             [currentUgen setAtype:'*'];
  127.             break;
  128.         }
  129.         case 8: {
  130.             currentUgen = [[Arith alloc] init];
  131.             [currentUgen setAtype:'/'];
  132.             break;
  133.         }
  134. /*
  135.         case 9: {
  136.             currentUgen = [[WS alloc] init];
  137.             break;
  138.         }
  139. */
  140.         case 10: {
  141.             currentUgen = [[Comb alloc] init];
  142.             break;
  143.         }
  144.         case 11: {
  145.             currentUgen = [[Pluck alloc] init];
  146.             break;
  147.         }
  148. /*        case 12: {
  149.             currentUgen = [[Allpass alloc] init];
  150.             break;
  151.         }
  152. */        case 13: {
  153.             currentUgen = [[Allpass alloc] init];     // delay actually?
  154.             break;
  155.         }
  156. /*        case 14: {
  157.             currentUgen = [[Reverb alloc] init];
  158.             break;
  159.         }
  160. */
  161.         case 15: {
  162.             currentUgen = [[Oscil alloc] init];
  163.             break;
  164.         }
  165.         case 16: {
  166.             currentUgen = [[Buzz alloc] init];
  167.             break;
  168.         }
  169.         case 17: {
  170.             currentUgen = [[Rand alloc] init];
  171.             break;
  172.         }
  173.         case 18: {
  174.             currentUgen = [[Evp alloc] init];
  175.             break;
  176.         }
  177.         case 19: {
  178.             currentUgen = [[Reson alloc] init];
  179.             break;
  180.         }
  181.         case 20: 
  182.         case 21: 
  183.         case 22: 
  184.         case 23: 
  185.         case 24: 
  186.         case 25:      {
  187.             currentUgen = [[Converter alloc] init];
  188.             [currentUgen setCtype:ugenType];
  189.             break;
  190.         }
  191.         default: {
  192.             NXRunAlertPanel("patchmix","Sorry, this unit generator is not yet working","OK",NULL,NULL);
  193.             return NO;
  194.         }
  195.     }
  196.     currentUgenCenter.x = currentUgenCenter.y = 40;
  197.   /* we accept it */
  198.     [self convertPoint:currentLocation fromView:nil]; 
  199.  
  200.    // center on the cursor 
  201.     currentLocation->x  -= [currentUgen getCenter]->x;
  202.     currentLocation->y  -= [currentUgen getCenter]->y;
  203.  
  204.     [currentUgen move:currentLocation];
  205.     currentLocation = [currentUgen getLocation];
  206.  
  207.     currentImage = [currentUgen getImage];
  208.     // draw the current ugen into the view 
  209.     [self lockFocus];
  210.     [currentImage composite:NX_SOVER toPoint:currentLocation];
  211.     [self unlockFocus];
  212.     [window flushWindow];
  213.  
  214.     // draw the current ugen into the off-screen buffer 
  215.     if ([screenImage lockFocus]) {
  216.     [currentImage composite:NX_SOVER toPoint:currentLocation];
  217.     [screenImage unlockFocus];
  218.     }
  219.  
  220.     
  221.     [window disableFlushWindow];
  222.         [self display];
  223.         [window reenableFlushWindow];
  224.  
  225.         return YES;
  226. }
  227.  
  228. - drawSelf:(NXRect *)rects :(int)count
  229. {
  230.     /* load the appropriate portion of the off-screen buffer
  231.      * into the visible portion of the view
  232.      */
  233.     [screenImage composite:NX_COPY fromRect:rects toPoint:&(rects->origin)];
  234.     return self;
  235. }
  236.  
  237.  
  238. - erase:sender
  239. //    erase the view and free up all the unit generators 
  240. {
  241.     
  242.     NXSize    imageSize;
  243.     NXPoint outLocation;
  244.     
  245.     setting = connecting = moving = NO;
  246.     
  247.     if ([screenImage lockFocus]) {
  248.     NXEraseRect(&bounds);
  249.     [screenImage unlockFocus];
  250.     }
  251.  
  252.     [Inst freeUgens];     // free up ugens in list
  253.         
  254.     currentUgen = [[Out alloc] init];
  255.  
  256.     // draw the out ugen into the view
  257.     currentImage = [currentUgen getImage];
  258.         [currentImage getSize:&imageSize];
  259.     outLocation.x = floor((NX_WIDTH(&bounds) - imageSize.width) / 2.0);
  260.        outLocation.y = floor((NX_HEIGHT(&bounds) - imageSize.height) / 5.0);
  261.     [currentUgen move:&outLocation];    
  262.         [self lockFocus];
  263.         [currentImage composite:NX_SOVER toPoint:&outLocation];
  264.         [self unlockFocus];
  265.         [window flushWindow];
  266.  
  267.     // draw the out ugen into the off-screen buffer 
  268.         if ([screenImage lockFocus]) {
  269.         [currentImage composite:NX_SOVER toPoint:&outLocation];
  270.         [screenImage unlockFocus];
  271.         }
  272.         [self display];
  273.  
  274.     
  275.         return self;    
  276. }
  277.  
  278. - mouseDown:(NXEvent *)e
  279. /*    logic for mouse down events:
  280.     convert the point location 
  281.     if a unit generator found at the mouse down point
  282.         if a parameter found at the mouse down point
  283.             if we are setting a parameter
  284.                 set the parameter to whatever use input into Param form field
  285.                 unhighlight the parameter
  286.             else if the event is a double click
  287.                 we are setting a parameter so highlight it
  288.                 diplay the parameter name and value in the Param form field
  289.             else
  290.                 we are connecting unit generators so save the location
  291.         else (a unit generator found, but no parameter)
  292.             if event is a double-click
  293.                 delete unit generator if user confirms and it is not an out ugen
  294.             else single-click
  295.                 if setting, user error - display panel
  296.                 else we are moving a unit generator - erase and redraw at location
  297.                     and erase all its connections
  298.     else no unit generator found
  299.         if setting - user error - display panel
  300.     while event is not a mouseUp,
  301.         call mouseDraggedAction (for moving unit generator)
  302. */
  303.  {
  304.      id pList;
  305.         NXPoint startPoint = e->location, nextPoint;
  306.         int looping = YES, i;
  307.        int oldMask = [window addToEventMask:NX_MOUSEDRAGGEDMASK];
  308.     
  309.         /* do first mouse down action */
  310.         [self convertPoint:&startPoint fromView:nil];    
  311. //printf("mouseDown\n");
  312.  
  313.     if(currentUgen = [Inst findUgenAtPoint:&startPoint]) {
  314.         currentImage = [currentUgen getImage];
  315.         if(currentParam = [currentUgen findParamAtPoint:&startPoint]) {
  316.             if(setting) {        // mouse click after set param val
  317.                 [currentParam setValue:[paramVal stringValueAt:0]];
  318.                 setting = NO;
  319.                 hrect = [currentParam getRect];  
  320.                             // unhighlight param
  321.                     [self lockFocus];
  322.                     NXHighlightRect(hrect);
  323.                     [self unlockFocus];
  324.                     [window flushWindow];
  325.             }
  326.             else if(e->data.mouse.click == 2) {         // double click, 
  327.         // begin to set param...
  328.                 connecting = moving = NO;
  329.                 setting = YES;
  330.                 hrect = [currentParam getRect];        // highlight the param
  331.                     [self lockFocus];
  332.                     NXHighlightRect(hrect);
  333.                     [self unlockFocus];
  334.                     [window flushWindow];
  335.                 [paramVal setStringValue:[currentParam getValue] at:0];
  336.                 [paramVal setTitle:[currentParam getTitle] at:0];
  337.                 [paramVal selectTextAt:0];
  338.             }
  339.             else {                             // no double click
  340.                 connecting = YES;
  341.                 moving = setting = NO;    
  342.                 connPoint1 = [currentParam getDrawPoint];
  343.                 connUgen1 = currentUgen;
  344.                 connParam1 = currentParam;
  345.             }
  346.         }
  347.         else {                // no param found,  but a ugen selected
  348.             if(e->data.mouse.click == 2) {         // double click, delete ugen?
  349.                 ugenselected = YES;
  350.                 hrect = [currentUgen getRect];    // highlight the ugen
  351.                     [self lockFocus];
  352.                     NXHighlightRect(hrect);
  353.                     [self unlockFocus];
  354.                     [window flushWindow];
  355.                 choice = NXRunAlertPanel("Cut Alert", "Delete this unit generator?", "Blow it away","No, Save it!",NULL);
  356.                 hrect = [currentUgen getRect];  
  357.     // unhighlight ugen
  358.                     [self lockFocus];
  359.                     NXHighlightRect(hrect);
  360.                     [self unlockFocus];
  361.                     [window flushWindow];
  362.                 if(choice == NX_ALERTDEFAULT) {
  363.                     if(!strcmp("Out",[currentUgen getType])) 
  364.                         NXRunAlertPanel("Cut Alert", "Can't delete Output Unit Generator!", "OK", NULL, NULL);
  365.                     else {
  366.                         if(![currentUgen remove]) {
  367.                             NXRunAlertPanel("Cut Alert", "Can't delete a connected unit generator! Please delete connectors first.", "OK", NULL, NULL);
  368.                         }
  369.                         else {
  370.                             //THIS ERASES A UGEN 
  371.                                 // draw the current ugen into the view 
  372.                                 [self lockFocus];
  373.                                 [[currentUgen getImage] composite:NX_XOR toPoint:[currentUgen getLocation]];
  374.                                [self unlockFocus];
  375.                                 [window flushWindow];
  376.                                 // draw the current ugen into the off-screen buffer 
  377.                                 if ([screenImage lockFocus]) {
  378.                                     [[currentUgen getImage] composite:NX_XOR toPoint:[currentUgen getLocation]];
  379.                                 [screenImage unlockFocus];
  380.                             }
  381.                         }
  382.                     }
  383.                     }
  384.                    [self display];
  385.             }
  386.             else {    // not a double-click, ugen selected
  387.                 if(setting)        {    // unhighlight param and stop setting - user error
  388.                         [self lockFocus];
  389.                         NXHighlightRect(hrect);
  390.                         [self unlockFocus];
  391.                         [window flushWindow];
  392.                     NXRunAlertPanel("Param Alert", "I hope you know you have to click on the param again to save the value...", "Oh, alright!", NULL, NULL);
  393.                     setting = NO;
  394.                 }
  395.                 else         {    // unit gen selected no param, not double click, not setting
  396.                     moving = YES;
  397.                     connecting = setting = NO;
  398.                             // erase the original so you can move image around
  399.                         [self lockFocus];
  400.                         [[currentUgen getImage] composite:NX_XOR toPoint:[currentUgen getLocation]];
  401.                        [self unlockFocus];
  402.                         [window flushWindow];
  403.                                 // draw the current ugen into the off-screen buffer 
  404.                         if ([screenImage lockFocus]) {
  405.                             [[currentUgen getImage] composite:NX_XOR toPoint:[currentUgen getLocation]];
  406.                         [screenImage unlockFocus];
  407.                     }
  408.                                 // erase the connectors too, for now
  409.                     pList = [currentUgen getParamList];
  410.                     for(i = 0; i < [pList  count]; i++)   {
  411.                         currentParam = [pList objectAt:i];
  412.                         if(eraseParam = [currentParam getConnectedParam])      {    // if connected
  413.                                 ePoint1 = [currentParam getDrawPoint];
  414.                                 ePoint2 = [eraseParam getDrawPoint];
  415.                                    [self lockFocus];
  416.                                  PSsetgray(NX_WHITE);
  417.                                 PSLine(ePoint1->x,ePoint1->y, ePoint2->x-ePoint1->x, ePoint2->y-ePoint1->y);
  418.                                 [self unlockFocus];
  419.                                    if ([screenImage lockFocus]) {
  420.                                      PSsetgray(NX_WHITE);
  421.                                     PSLine(ePoint1->x,ePoint1->y, ePoint2->x-ePoint1->x, ePoint2->y-ePoint1->y);
  422.                                     [screenImage unlockFocus];
  423.                                 }
  424.                         }
  425.                     }
  426.                                 // draw ugen where mouse down is and store points
  427.                         nextPoint.x  = startPoint.x - currentUgenCenter.x;
  428.                          nextPoint.y  = startPoint.y - currentUgenCenter.y;
  429.                             // draw the current ugen into the view 
  430.                         [self lockFocus];
  431.                        [currentImage composite:NX_SOVER toPoint:&nextPoint];
  432.                         [self unlockFocus];
  433.                         [window flushWindow];
  434.                         if ([screenImage lockFocus]) {
  435.                             [currentImage composite:NX_SOVER toPoint:&nextPoint];
  436.                             [screenImage unlockFocus];
  437.                         }
  438.                     erasePoint1.x = nextPoint.x;
  439.                     erasePoint1.y = nextPoint.y;
  440.                 }
  441.             }
  442.         }
  443.     }
  444.     // no ugen found
  445.     else {    
  446.         if(setting)        {    // unhighlight param and stop setting - user error
  447.                 [self lockFocus];
  448.                 NXHighlightRect(hrect);
  449.                 [self unlockFocus];
  450.                 [window flushWindow];
  451.             NXRunAlertPanel("Param Alert", "I hope you know you have to click on the param again to save the value...", "Oh, alright!", NULL, NULL);
  452.             setting = NO;
  453.         }
  454.     }    
  455.  
  456.        while (looping)        {
  457.         e = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
  458.         nextPoint = e->location;        
  459.             [self convertPoint:&nextPoint fromView:nil]; 
  460.         if(e->type == NX_MOUSEDRAGGED)    {
  461.                 [superview autoscroll:e];
  462.                                     /* TO DRAG AN IMAGE:  */
  463.             if(moving)     {        // erase the old
  464.                     [self lockFocus];
  465.                     [currentImage composite:NX_XOR toPoint:&erasePoint1];
  466.                     [self unlockFocus];
  467.                     [window flushWindow];
  468.                 // erase off-screen buffer, not needed if not drawing there 
  469.                     if ([screenImage lockFocus]) {
  470.                     [currentImage composite:NX_XOR toPoint:&erasePoint1];
  471.                     [screenImage unlockFocus];
  472.                     }
  473.                 // do continuing mouse dragged action 
  474.                     [self mouseDraggedAction:&nextPoint];
  475.             }
  476.         }
  477.         else {            //     mouse up - drag is done
  478.                 looping = NO;
  479.                                     /* do mouse up action */
  480.                 [self mouseUpAction:&nextPoint];
  481.                 [window setEventMask:oldMask];
  482.         }    
  483.     
  484.     }
  485.         return self;
  486.  }
  487.  
  488. - mouseDraggedAction:(NXPoint *)currentLocation
  489. {
  490. //    THIS DRAGS A UGEN:   draws ugen on new points  */
  491.     if (moving)     {
  492.             currentLocation->x  -= currentUgenCenter.x;
  493.             currentLocation->y  -= currentUgenCenter.y;
  494.                 // draw the current ugen into the view 
  495.             [self lockFocus];
  496.            [currentImage composite:NX_SOVER toPoint:currentLocation];
  497.             [self unlockFocus];
  498.             [window flushWindow];
  499.             //  draw the current ugen into the off-screen buffer 
  500.             if ([screenImage lockFocus]) {
  501.                 [currentImage composite:NX_SOVER toPoint:currentLocation];
  502.                 [screenImage unlockFocus];
  503.             }
  504.         erasePoint1.x = currentLocation->x;
  505.         erasePoint1.y = currentLocation->y;
  506.     }
  507.     return self;
  508. }
  509.  
  510. - mouseUpAction:(NXPoint *)currentLocation
  511. /*    if moving
  512.         redraw the connections to other unit generators
  513.     else if connecting
  514.         for each parameter:
  515.             erase previous connections
  516.             draw the new connection
  517.             store the new connections
  518. */        
  519. {
  520.     id pList;
  521.     BOOL draw = YES;
  522.     int i;
  523.     
  524.     if(moving)     {    
  525.                     //    for each param, redraw if connected
  526.                     //    save new location for Ugen
  527.             currentLocation->x  -= currentUgenCenter.x;
  528.             currentLocation->y  -= currentUgenCenter.y;
  529.         [currentUgen move:currentLocation];
  530.                     //    if ugen connected, redraw connectors
  531.                     //        for each param, check if connected, redraw line
  532.         pList = [currentUgen getParamList];
  533.         for(i = 0; i < [pList  count]; i++)    {
  534.             currentParam = [pList objectAt:i];
  535.             if(connParam1 = [currentParam getConnectedParam])      {    // if connected
  536.                     connPoint1 = [currentParam getDrawPoint];
  537.                     connPoint2 = [connParam1 getDrawPoint];
  538.                        [self lockFocus];
  539.                     PSLine(connPoint1->x,connPoint1->y, connPoint2->x-connPoint1->x, connPoint2->y-connPoint1->y);
  540.                     [self unlockFocus];
  541.                        if ([screenImage lockFocus]) {
  542.                         PSLine(connPoint1->x,connPoint1->y, connPoint2->x-connPoint1->x, connPoint2->y-connPoint1->y);
  543.                         [screenImage unlockFocus];
  544.                     }
  545.             }
  546.         }
  547.         [self display];
  548.         moving = NO;
  549.     }
  550. //  if connecting draw final line
  551.     else if(connecting) {
  552.         if((currentUgen = [Inst findUgenAtPoint:currentLocation]) != connUgen1) {
  553.                     // test if these connectors are already connected
  554.                     //     if so, erase the line 
  555.                     // erase any previous connections for either connector
  556.             if(currentParam = [currentUgen findParamAtPoint:currentLocation]) {
  557.                 connPoint2 = [currentParam getDrawPoint];
  558.                 if([connParam1 getConnectedParam] == currentParam) {
  559.                                     // they are already connected, ERASE
  560.                                     // and disconnect
  561.                                     //printf("already conn, erasing\n");
  562.                     [connParam1 setConnectedParam:nil];
  563.                     [currentParam setConnectedParam:nil];
  564.                        [self lockFocus];
  565.                      PSsetgray(NX_WHITE);
  566.                     PSLine(connPoint1->x,connPoint1->y, connPoint2->x-connPoint1->x, connPoint2->y-connPoint1->y);
  567.                     [self unlockFocus];
  568.                        if ([screenImage lockFocus]) {
  569.                          PSsetgray(NX_WHITE);
  570.                         PSLine(connPoint1->x,connPoint1->y, connPoint2->x-connPoint1->x, connPoint2->y-connPoint1->y);
  571.                         [screenImage unlockFocus];
  572.                     }
  573.                     draw = NO;
  574.                 }                            // conn1 was connected, erase
  575.                 else  {
  576.                    if(eraseParam = [connParam1 getConnectedParam]) {
  577.                     ePoint2 = [eraseParam getDrawPoint];
  578.                     [connParam1 setConnectedParam:nil];
  579.                     [eraseParam setConnectedParam:nil];
  580.                        [self lockFocus];
  581.                      PSsetgray(NX_WHITE);
  582.                     PSLine(connPoint1->x,connPoint1->y, ePoint2->x-connPoint1->x, ePoint2->y-connPoint1->y);
  583.                     [self unlockFocus];
  584.                        if ([screenImage lockFocus]) {
  585.                          PSsetgray(NX_WHITE);
  586.                         PSLine(connPoint1->x,connPoint1->y, ePoint2->x-connPoint1->x, ePoint2->y-connPoint1->y);
  587.                         [screenImage unlockFocus];
  588.                     }
  589.                    }                        // conn2 was connected, erase
  590.                    if(eraseParam = [currentParam getConnectedParam]) {
  591.                     ePoint1 = [eraseParam getDrawPoint];
  592.                     [currentParam setConnectedParam:nil];
  593.                     [eraseParam setConnectedParam:nil];
  594.                        [self lockFocus];
  595.                      PSsetgray(NX_WHITE);
  596.                     PSLine(ePoint1->x,ePoint1->y, connPoint2->x-ePoint1->x, connPoint2->y-ePoint1->y);
  597.                     [self unlockFocus];
  598.                        if ([screenImage lockFocus]) {
  599.                          PSsetgray(NX_WHITE);
  600.                         PSLine(ePoint1->x,ePoint1->y, connPoint2->x-ePoint1->x, connPoint2->y-ePoint1->y);
  601.                         [screenImage unlockFocus];
  602.                     }
  603.                    }
  604.                 }    
  605.                 if(draw) {                // draw the connnector
  606.                     [connParam1 setConnectedParam:currentParam];
  607.                     [currentParam setConnectedParam:connParam1];
  608.                        [self lockFocus];
  609.                     PSLine(connPoint1->x,connPoint1->y, connPoint2->x-connPoint1->x, connPoint2->y-connPoint1->y);
  610.                     [self unlockFocus];
  611.                        if ([screenImage lockFocus]) {
  612.                         PSLine(connPoint1->x,connPoint1->y, connPoint2->x-connPoint1->x, connPoint2->y-connPoint1->y);
  613.                         [screenImage unlockFocus];
  614.                         }
  615.                 }
  616.             }
  617.             [self display];
  618.             connecting = NO;
  619.         }
  620.     }
  621.         return self;
  622. }
  623.  
  624. /* delegation methods */
  625. - acceptedWindow:acceptView fromSource:source
  626. {
  627.   /*
  628.    * if delegate implements this method, it'll get called whenever the user
  629.    * drops a window into the view
  630.    */
  631.     return self;
  632. }
  633.  
  634. @end
  635.